home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Network Support Library
/
RoseWare - Network Support Library.iso
/
btrieve
/
tpbtrv.arc
/
BTRIEVE.ASM
next >
Wrap
Assembly Source File
|
1988-04-22
|
12KB
|
247 lines
;-----------------------------------------------------------------------------
;
; This routine interfaces between Turbo Pascal programs and Btrieve
; assembly routines. This is a modified version for use with
; Mulkey.PAS which passes the key buffer length to Btrieve. To use
; without this feature, remove references to KeyLen in the stack
; structure below, force 255 in each call to Btrieve and rewrite the
; parameter list to Btrv.
;
; Copyright 1988 by Mark R. Boler - All Rights Reserved
;
;-----------------------------------------------------------------------------
;
; This module is optimized primarily for the 80386 processor,
; secondary to that, the 80286 processor. The 8088/8086 processors
; would benefit from a different algorithm for loading the parameters
; to the Btrieve data buffer. The format used here is:
;
; push [bp + xx]
;
; This executes in about 5 clocks on the 80286 and 80386 processors
; and about 25 clocks on the 8086 and about 33 clocks on the 8088 with
; the added benefit of not having to explicitly subtract sp plus the
; fact that the push opcodes take less code space.
;
; The 8088/8086 processors should use:
;
; mov ax, [bp + xx]
; mov [bp - xx], ax
;
; This executes in about 20 clocks on the 8086 and 28 clocks on the
; 8088 because when loading to/from the ax register, no EA calculation
; is needed. The reason this was not used on the 80286/80386 is because
; on these procesors, this takes about 8 and 6 clocks respectively and
; I liked the 5 and 5 clocks of the push mem16 method better. This may
; make it harder to read but the Btrieve interface is called quite
; repetitively in database applications and this was a good place to
; do some major optimizing.
;
;-----------------------------------------------------------------------------
TITLE BTRIEVE ; modified for Mulkey
DATA SEGMENT WORD PUBLIC
ASSUME DS:DATA
ProcID DW ? ; process Id for BMulti
Version DW ? ; single/multi ProcID/No ProcID
DATA ENDS
CODE SEGMENT WORD PUBLIC
ASSUME CS:CODE
PUBLIC Btrv, InitBtrv
; FUNCTION Btrv(Op: WORD; MODIFIED FOR KEY LENGTH PASSING
; VAR PosBlock;
; VAR Data;
; VAR DataLen: WORD;
; VAR KBuf;
; Key: BYTE;
; KeyLen: BYTE): WORD; EXTERNAL;
StackRec STRUC ; stack structure
;
; These are the local variables passed to Btrieve as a data block
; ---------------------------------------------------------------------
DBuf DD ? ; address of data buffer
BufLen DW ? ; data buffer length
PosInfo DD ? ; address of positioning info
FCB DD ? ; address of FCB
OpCode DW ? ; operation code
KBuf DD ? ; address of key buffer
KeyLength DB ? ; length of key buffer
KeyNumber DB ? ; key number
StatusAddr DD ? ; address of status word
XFaceID DW ? ; interface id 'va' for variable
;
; This is the Status word that Btrieve uses to return the status info
; ---------------------------------------------------------------------
Status DW ? ; Status word
;
; This is the return address
; ---------------------------------------------------------------------
RetAddr DD ? ; procedure far return address
;
; These are the parameters passed to this function
; ---------------------------------------------------------------------
KeyLen DB ? ; key buffer length (byte)
KeyLenFill DB ? ; byte filler
KeyNum DB ? ; key number (byte)
KeyNumFill DB ? ; byte filler
KeyBufOfs DW ? ; offset address of key buffer
KeyBufSeg DW ? ; segment address of key buffer
DataLen DD ? ; address of data length word
DataBufOfs DW ? ; offset address of data buffer
DataBufSeg DW ? ; segment address of data buffer
PosBlock DD ? ; address of position block
Function DW ? ; Btrieve function number
StackRec ENDS
StackF EQU [bp - RetAddr] ; reference to stack frame [bp]
MinDosVer EQU 3 ; minimum DOS version for multi-user
PosOfs EQU 38 ; positioning info offset in PosBlock
VarID EQU 6176H ; variable data buffer ID ('va')
BtrErr EQU 20 ; Return value when Btrieve not loaded
MultiF EQU 0ABH ; Code for multi function Btrieve
BtrOffset EQU 033H ; offset of vector if Btrieve loaded
VersionL EQU BYTE PTR es:Version ; low byte of Version with es segment
BtrInt EQU 07BH ; Interrupt vectors
Btr2Int EQU 02FH ; " "
ZInt EQU 07FH ; " "
Btrv PROC FAR ; the Btrv function
mov si, bp ; save bp in si
mov bp, sp ; set up stack frame
mov cx, Version ; get version into cx
or cl, cl ; see if Btrieve was found during init
jz SHORT NotLoaded ; jump if not loaded
; allocate space for the Status word
sub sp, SIZE Status ; allocate the stack space
mov bx, sp ; save the offset in bx
; store the interface ID
mov ax, VarID ; get variable records interface ID
push ax ; store it
; store the address of the status word
push ss ; store the segment
push bx ; and the offset
; store the key number and key buffer size
mov al, StackF.KeyLen ; get length of key buffer
mov ah, StackF.KeyNum ; get key number
push ax ; and store them
; store the address of the key buffer
push StackF.KeyBufSeg ; store segment of key buffer
push StackF.KeyBufOfs ; store offset of key buffer
; store the Btrieve operation code
push StackF.Function ; store the op code
; calculate and store positioning and FCB addresses
les ax, StackF.PosBlock ; es:ax => pos block
push es ; store FCB segment
push ax ; store FCB offset
push es ; store positioning info segment
add ax, PosOfs ; adjust positioning info offset
push ax ; store positioning info offset
; store data buffer length
les bx, StackF.DataLen ; es:[bx] = data buffer length word
push es:[bx] ; store the length
; store data buffer address
push StackF.DataBufSeg ; store data buffer segment
push StackF.DataBufOfs ; store data buffer offset
; set up call to Btrieve, make ds:[dx] = data block for Btrieve
mov di, ds ; save ds in di for now
mov dx, sp ; stack pointer is data block offset
mov ax, ss ; make ds = stack segment
mov ds, ax
; see which version to call and do it
or ch, ch ; see if it is single or multi-user
je SHORT NotMulti ; then jump around multi code if single
; make the call to multi-user btrieve
MakeCall:
mov es, di ; copy our saved ds into es for now
mov ax, cx ; set up ax with Version word from cx
mov bx, es:ProcID ; set Process ID for BMulti
int Btr2Int ; call it
or al, al ; see if it is zero
jz SHORT DoneCall ; if so then jump ahead
mov ax, 0200H
int ZInt ; make the interrupt
jmp SHORT MakeCall ; then loop
DoneCall:
test cl, 00000010B ; should we set the process ID
jnz SHORT SetDBuf ; if not then jump
mov es:ProcID, bx ; otherwise store the new process ID
inc cx ; we have process ID
mov VersionL, cl ; set version for next time around
jmp SHORT SetDBuf ; then jump around single-user code
NotLoaded:
mov ax, BtrErr ; set error code
jmp SHORT Done ; and return
NotMulti:
int BtrInt ; process request for single-user
SetDBuf:
mov ds, di ; get our data segment back from di
mov bx, sp ; ss:[bx] = data block
mov ax, ss:[bx].BufLen ; load data buffer length into ax
les bx, StackF.DataLen ; es:[bx] = data length word
mov es:[bx], ax ; store the data buffer length
mov ax, StackF.Status ; set function return code
Done:
mov sp, bp ; de-allocate local data (pushed)
mov bp, si ; restore bp from si
ret 22 ; clean up and return to caller
Btrv ENDP
InitBtrv PROC NEAR
mov ax, 3500H + BtrInt ; DOS get interrupt vector function
int 21H ; offset comes back in bx
xor dx, dx ; clear out dx
cmp bx, BtrOffset ; is Btrieve resident
jne SHORT IDone ; jump if not and set Version
inc dx ; make dx = 1
mov ah, 30H ; check the DOS version number
int 21H ; call DOS
cmp al, MinDosVer ; DOS major version number
jb SHORT IDone ; if < DOS 3.xx then set Version
mov al, dh ; clear out al
mov ah, MultiF ; see if it is multi-user version
int Btr2Int ; see what Btrieve tells us it is
cmp al, 'M' ; is it a multi-user version
jne SHORT IDone ; jump if it is
mov dh, ah ; set to multi-user
IDone:
mov ds:Version, dx ; store dx into version
ret ; return to caller
InitBtrv ENDP
CODE ENDS
END